import { TEXT } from '@/api/const';
import { ContentTypeEnum } from '@/enums/httpEnum';
import { useGlobSetting } from '@/hooks/setting';
import { useMessage } from '@/hooks/web/useMessage';
import { createAxios } from '@/utils/axios';
import { AxiosRequestConfig } from 'axios';
import { getToken } from './auth';
import { AxiosTransform, UploadFileParams } from './axios/types';

const headerAuth = 'Token';

const { createMessage, createErrorModal } = useMessage();

const transform: AxiosTransform = {
	// 请求拦截器
	requestInterceptors: (config, options) => {
		const token = getToken();
		if (token && (config as Recordable)?.requestOptions?.withToken) {
			(config as Recordable).headers[headerAuth] = options.authenticationScheme
				? `${options.authenticationScheme} ${token}`
				: token;
		}
		return config;
	},
	// 处理请求成功后的数据
	transformRequestHook: (res, options) => {
		const { isTransformResponse, isReturnNativeResponse } = options;
		// 是否返回原生响应头 比如：需要获取响应头时使用该属性(下载文件流获取文件名)
		if (isReturnNativeResponse) {
			return res;
		}
		// 不进行任何处理，直接返回
		// 用于页面代码可能需要直接获取code，data，message这些信息时开启
		if (!isTransformResponse) {
			return res.data;
		}
		const { data } = res;
		if (!data) {
			throw new Error('请求失败');
		}
		const { code, data: innerData, msg, message } = data;
		if (code === 0) {
			return innerData;
		}

		// errorMessageMode='modal' 的时候会显示modal错误弹窗，而不是消息提示，用于一些比较重要的错误
		// errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
		if (options.errorMessageMode === 'modal') {
			createErrorModal({ title: '错误提示', content: msg || message });
		} else if (options.errorMessageMode === 'message') {
			createMessage.error(msg || message || TEXT.SERVER_ERROR);
		}

		return Promise.reject(msg || message || TEXT.SERVER_ERROR);
	},

	// 请求错误处理
	// responseInterceptorsCatch: error => {},
};

/**
 * @example createAxios({ transform, requestOptions: { urlPrefix: '/dmsApi' } });
 */
export const defHttp = createAxios({ transform });

export function upload<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
	const formData = new FormData();
	const customFilename = params.name || 'file';
	const { uploadUrl } = useGlobSetting();
	if (!config.url && uploadUrl) {
		config.url = uploadUrl;
	}

	if (params.filename) {
		formData.append(customFilename, params.file, params.filename);
	} else {
		formData.append(customFilename, params.file);
	}

	if (params.data) {
		Object.keys(params.data).forEach(key => {
			const value = params.data![key];
			if (Array.isArray(value)) {
				value.forEach(item => {
					formData.append(`${key}[]`, item);
				});
				return;
			}

			formData.append(key, params.data![key]);
		});
	}

	return defHttp.post<T>({
		...config,
		params: formData,
		headers: {
			'Content-type': ContentTypeEnum.FORM_DATA,
		},
	});
}
